package com.platform.tony.config;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.sql.DataSource;

/**
 * spring security 核心配置
 */
@Slf4j
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private DataSource dataSource;
    /**
     * 错误信息提示
     */
    @Bean
    public ReloadableResourceBundleMessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource =
                new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:org/springframework/security/messages_zh_CN");
        return messageSource;
    }
    /**
     * 身份认证接口
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(detailsService()).passwordEncoder(passwordEncoder());
    }
    /**
     * AuthenticationManager
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    /**
     * 持久化令牌桶 内存和数据库的方式 InMemoryTokenRepositoryImpl node = new InMemoryTokenRepositoryImpl();
     */
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl node = new JdbcTokenRepositoryImpl();
        node.setCreateTableOnStartup(false);
        node.setDataSource(dataSource);
        return node;
    }

    /**
     * 核心配置
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 配置 authorize
        http.authorizeRequests()
                .antMatchers("/**/*.js", "*.jpg", "/**/*.css").permitAll()
                .antMatchers("/login", "/login/form").permitAll()
                .mvcMatchers("/vc.jpg").permitAll()
                .anyRequest().authenticated();
        // 登录页面 form login
        http.formLogin()
                .loginPage("/login") // 登录页面
                .loginProcessingUrl("/login/form")   // 登录请求访问路径
                // .defaultSuccessUrl("/home", true) // 登录成功跳转路径 重定向
                .successForwardUrl("/home")  // 请求转发
                .failureForwardUrl("/login")
                // 成功和失败的处理器 .successHandler() .failureHandler()
                .passwordParameter("password")
                .usernameParameter("username");
        // logout 配置
        http.logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("logout", "GET")) // .logoutUrl("logout")
                .invalidateHttpSession(true)
                .clearAuthentication(true);
        // session 管理
        http.sessionManagement().maximumSessions(20);
        // 权限不足 .accessDeniedHandler()
        http.exceptionHandling().accessDeniedPage("/403");
        // 记录登录
        http.rememberMe()
                .rememberMeParameter("rememberMe")
                .tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(30 * 60)
                .userDetailsService(detailsService());
        // 关闭 csrf 攻击 开启跨域访问
        http.csrf().disable().cors().disable();
        // 防止 iframe 造成跨域
        http.headers().frameOptions().disable();
        // 禁用缓存
        http.headers().cacheControl();
        // 添加动态验证码
        http.addFilterAt(kaptchaFilter(), UsernamePasswordAuthenticationFilter.class);


    }

    @Bean
    public KaptchaFilter kaptchaFilter() throws Exception {
        KaptchaFilter kaptchaFilter = new KaptchaFilter();
        //指定接收验证码请求参数名
        kaptchaFilter.setKaptcha("kaptcha");
        kaptchaFilter.setPostOnly(false);
        //指定认证管理器
        kaptchaFilter.setAuthenticationManager(authenticationManagerBean());
        //指定认证成功和失败处理
        // kaptchaFilter.setAuthenticationSuccessHandler(new MyAuthenticationSuccessHandler());
        // kaptchaFilter.setAuthenticationFailureHandler(new MyAuthenticationFailureHandler());
        //指定处理登录
        kaptchaFilter.setFilterProcessesUrl("/login/form");
        kaptchaFilter.setUsernameParameter("username");
        kaptchaFilter.setPasswordParameter("password");
        return kaptchaFilter;
    }
    // 密码处理器
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }
    // 资源配置
    @Override
    public void configure(WebSecurity web) throws Exception {
        //放行静态资源
        web.ignoring()
                .antMatchers(HttpMethod.GET,
                        "/swagger-resources/**",
                        "/PearAdmin/**",
                        "/component/**",
                        "/admin/**",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js",
                        "/swagger-ui.html",
                        "/webjars/**",
                        "/v2/**",
                        "/druid/**");

    }



    @Bean
    public UserDetailsService detailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        UserDetails build1 = User.withUsername("admin").password("123456").roles("USER").build();
        UserDetails build2 = User.withUsername("user").password("123456").roles("USER").build();
        manager.createUser(build1);
        manager.createUser(build2);

        return manager;
    }





}
